-- us核心库文件
-- Author: Colocasia
-- Date: 2019-07-03

local skynet = require "skynet";
require 'skynet.manager';
local cluster = require 'skynet.cluster';

local log = require 'log';
local core = require 'us.core';
local string = require 'us.string';
local table = require 'us.table';
local table_unpack = table.unpack;
local table_concat = table.concat;

local us = {}


local SEND_SESSION_NO_RET = 0;


---错误处理
local function on_cmd_err(msg)
    log.error(msg);
end

---启动服务
function us:start(module, name, func, ...)
    if not module then return false end
    local args = {...}

    if "table" == type(module) then
    elseif "string" == type(module) then
        name = name or module;
        _, module = xpcall(require, on_cmd_err, module);        
    elseif "function" == type(module) then
        _, module, name = xpcall(module, on_cmd_err);
    else
        log.fatal("start module type is %s", type(module));
        return false;
    end

    if not name then
        name = "S"..string.trim(string.split(string.format("%s", module), ':')[2]);
        log.warning("service start name is null, generate name %s", name);
    end
    local function _init()
        skynet.register(name);
        skynet.dispatch("lua", function(session, source, cmd, ...)
            -- skynet.trace()
            local f = module[cmd]
            local function ret(ok, ...)
                if session ~= SEND_SESSION_NO_RET then
                    skynet.retpack(...)
                end
            end
            ret(xpcall(f, on_cmd_err, module, ...));
        end)

        if "function" == type(func) then
            func(module, name, table_unpack(args));
            -- log.debug("service %s callback", name);
        end
        log.notice("service %s start ok", name);
    end
    skynet.start(_init);
    return true;
end


---节点远程调用(call)
function us:call(server, service, ...)
    local ok, result;
    if server then
        ok, result = pcall(cluster.call, server, service, ...)
    else
        ok, result = pcall(skynet.call, service, ...)
    end

    if ok then
        return result;
    else
        log.warning("call server->%s service->%s faild! cmd->%s", server, service, ...);
        return nil;
    end
end


---节点远程调用(send)
function us:send(server, service, ...)
    local ok, result;
    if server then
        ok, result = pcall(cluster.send, server, service, ...)
    else
        ok, result = pcall(skynet.send, service, ...)
    end

    if ok then
        return result;
    else
        log.warning("send server->%s service->%s faild! cmd->%s", server, service, ...);
        return nil;
    end
end


---获取本服务地址
function us:self()
    return skynet.self()
end


---获取guid
function us:guid()
    local guid = core.guid();
    guid = string.gsub(guid, ".", function (c)
        return string.format("%02x", string.byte(c))
    end)
    return guid;
end

return us;
